﻿using AuthTemplate.DTO.User;
using AuthTemplate.Entity;
using AuthTemplate.Entity.Common;
using AuthTemplate.Infrastructure;
using AuthTemplate.Infrastructure.AutoMapper;
using AuthTemplate.Infrastructure.Token;
using AuthTemplate.Repository.Interface;
using AuthTemplate.Repository.Interface.IEntityRepository;
using AuthTemplate.Repository.Repositories;
using AuthTemplate.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AuthTemplate.Service
{
    public class UserService :BaseService, IUserService
    {
        private readonly IUserRepository userRepository;
        private readonly IRelevanceRepository relevanceRepository;
        private readonly IUnitOfWork unitOfWork;
        public UserService(IUserRepository userRepository,
            IRelevanceRepository relevanceRepository,
            IUnitOfWork unitOfWork)
        {
            this.userRepository = userRepository;
            this.relevanceRepository = relevanceRepository;
            this.unitOfWork = unitOfWork;
        }

        public LoginOutput Login(LoginInput input)
        {
            LoginOutput output = new LoginOutput();

            User user = new User();
            bool result = CheckUserPassword(input.Account, input.Password, out user);
            if (result && user.Status == 1)
            {
                string userRole = "";
                var relevances = relevanceRepository.FindBy(s => s.KeyType == RelevanceType.USERROLE && s.FirstId==user.Id && s.Status==1).ToList();
                relevances.ForEach(s => { userRole += s.SecondId + ","; });

                TokenInfo info = new TokenInfo()
                {
                    UserID = user.Id,
                    UserName = user.Account,
                    UserRole = userRole
                };
                string token = CommonToken.GetToken(info);
                output.token = token;
                output.userName = user.Name;
            }
            else
            {
                throw new Exception("用户名或密码错误");
            }
            return output;
        }

        public void AddUser(AddUserInput input)
        {
            User user = null;
            if(IsExistUser(input.Account , out user))
            {
                throw new Exception("账户已被注册");
            }
            
            string salt = "";
            string hashPassword = HashEncode.HashSaltEncoding(input.Password, out salt);
            user = input.Map<User>();
            user.Password = hashPassword;
            user.Salt = salt;
            user.CreateTime = DateTime.Now;

            userRepository.Add(user);
            unitOfWork.Commit();
        }

        public void ChangeUserPwd(ChangeUserPwdInput input)
        {
            User user = new User();
            bool result = CheckUserPassword(input.Account, input.OldPassword, out user);
            if(result == true)
            {
                string salt = "";
                string hashPassword = HashEncode.HashSaltEncoding(input.NewPassword, out salt);
                user.Password = hashPassword;
                user.Salt = salt;

                userRepository.Edit(user);
                unitOfWork.Commit();
            }
        }

        private bool CheckUserPassword( string account ,string password ,out User user)
        {
            if( !IsExistUser(account , out user))
            {
                return false;
            }

            string hashPassword = HashEncode.HashSaltEncoding(password , user.Salt);
            if (account == user.Account && hashPassword == user.Password)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private bool IsExistUser(string account , out User user)
        {
            user = userRepository.FindBy(s => s.Account == account).FirstOrDefault();
            if (user == null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
            
    }
    
    public interface IUserService
    {
        LoginOutput Login(LoginInput input);

        void AddUser(AddUserInput input);

        void ChangeUserPwd(ChangeUserPwdInput input);
    }
}
